home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
GNUUCP_2
/
SOURCE
/
SYSDEP.MSD
< prev
next >
Wrap
Text File
|
1989-07-31
|
14KB
|
657 lines
/*
* @(#)sysdep.msdos 1.6 87/09/23 Copyright 1987 Free Software Foundation, Inc.
*
* Copying and use of this program are controlled by the terms of the
* GNU Emacs General Public License.
*/
#ifndef lint
char sysdep_version[] = "@(#)sysdep.msdos gnuucp Version hoptoad-1.6";
#endif
/* Microsoft DOS */
#include "includes.h"
#include "uucp.h"
#include "sysdep.h"
/* Structure for find first/next (find()).
* NOTE: the DPB pointer is a double word
* character pointer; here it is declared as a
* long, to avoid problems with the various
* size of char *'s.
*/
struct _xfbuf {
char s_attrib; /* Search attribute */
/* These do not need to be initialized */
char drive; /* 0 == current, 1 == A: ... */
char fcbname[11]; /* FCB name, */
unsigned ent;
long dpb_ptr;
unsigned dirstart;
/* These are returned by DOS */
char f_attrib; /* found attribute, */
unsigned time; /* Packed time, */
unsigned date; /* Packed date */
long fsize; /* file size, */
char name[13]; /* found name */
};
#define GET_TIME 0x2c /* DOS function number for get_time */
#define DOS_INT 0x21 /* DOS interrupt number */
typedef struct timetype {
unsigned hour;
unsigned minute;
unsigned sec;
unsigned hsec;
} TIME, *TIME_PTR;
/*
* Note that NAMESIZE should be the max length of a file name, including
* all its directories, drive specifiers, extensions, and the like.
* E.g. on a Unix with 14-char file names, NAMESIZE is several hundred
* characters, since the 14-char names can be nested.
*/
/* FIXME, these should all be uppercase. */
/* FIXME, these are duplicated from includes.h */
#define FNAMESIZE sizeof("FILENAME") /* 8 chars */
#define NAMESIZE 128 /* full path size */
#define UFNAMESIZE 5 /* uux id size */
/* Our variables */
char hayesinit[] = "\r\r\rATZX1S0=1\r";
int fdtty; /* File descriptor for tty line */
void sigint(); /* Forward declaration */
/*
* Translation between integer baud rates and Unix baud rates (grumble)
*/
static struct baudtab {
int baudrate, damn_B_code;
} baudtab[] = {
50, B50,
75, B75,
110, B110,
134, B134,
150, B150,
200, B200,
300, B300,
600, B600,
1200, B1200,
1800, B1800,
2400, B2400,
4800, B4800,
9600, B9600,
19200, B19200,
38400, B38400,
};
static int
damn_B(baud)
{
register struct baudtab *b;
for (b = baudtab; b->baudrate < baud; b++) continue;
if (b->baudrate == baud)
return b->damn_B_code;
return EXTB; /* Maybe this'll get clocking from the modem */
}
/*
* Open the serial line for an incoming call.
* Argument of NULL or empty string means stdin.
*/
int
openline(ttynam, baud)
char *ttynam;
int baud;
{
int ontheline = !(ttynam && ttynam[0]); /* FIXME, this is garbage */
#ifndef COMPORT
if ((fdtty = open(ttynam, O_RDWR)) < 0)
{
printf("Cannot open %s for read/write %d\n",
ttynam, errno);
exit(1);
}
#else
set_tty(COMM1, damn_B(baud), CS8, MENBL);
printf("uucico : initializing modem.\n");
xwrite(hayesinit, sizeof(hayesinit)-1);
printf("uucico : waiting for call\n");
while ((get_msr() & CD) == 0) {
if (kbhit() != 0) {
printf("uucico : aborting at user's request.");
set_tty(0,0,0,MDSBL); /* Hang up */
sleep(2);
reset_tty();
exit(1);
}
}
printf("uucico : inbound call detected\n");
init_comm();
inp_flush();
sleep(2);
#endif
signal(SIGINT,sigint);
return SUCCESS;
}
/*
* openout() -- open line for dialout
*/
int
openout(ttynam, baud)
char *ttynam;
int baud;
{
#ifdef COMPORT
set_tty(COMM1, damn_B(baud), CS8, MENBL);
DEBUG(2,"initializing modem.\n", 0);
xwrite(hayesinit, sizeof(hayesinit)-1);
init_comm();
inp_flush();
sleep(2);
#else
if ((fdtty = open(ttynam, O_RDWR)) < 0)
{
if (debug > 0) {
printf("Cannot open %s for read/write %d\n",
ttynam, errno);
}
exit(1);
}
FIXME, do stty() here.
#endif
signal(SIGINT,sigint);
return SUCCESS;
}
/*
* Basement level I/O routines
*
* xwrite() writes a character string to the serial port
* xgetc() returns a character from the serial port, or an EOF for timeout.
* sigint() restores the state of the serial port on exit.
* hangup() hangs up the 'fone (e.g. drops DTR).
*/
void
sigint()
{
/* Restore terminal settings on dialout line */
hangup();
exit(0);
}
xwrite(buf,ctr)
char *buf;
int ctr;
{
int i;
#ifndef COMPORT
return write(fdtty,buf,ctr);
#else
for (i=0;i<=ctr;i++) {
outp_char(buf[i]);
}
return ctr;
#endif
}
/*
* Serial port reading routine
*/
int
xgetc()
{
char data;
#ifndef COMPORT
/* Warning: No timeouts... */
read(fdtty,&data,1);
return(data & 0xFF);
#else
int i;
unsigned s;
TIME n;
i = 0;
get_time(&n);
s = n.sec;
/*
* Implement timeouts by staring at the clock while we wait.
* When the second hand moves, bump our counter. This is a lot
* easier than figuring out the time when we'd time out (in hours,
* minutes, and seconds!) and comparing against that, which is
* what people tend to do in Unix where the time is just an integer
* number of seconds.
*/
while (i < BYTE_TIMEOUT) {
while (s == n.sec) {
if(inp_cnt() != 0) {
data = inp_char();
return (data & 0xFF);
}
get_time (&n);
}
s = n.sec;
++i;
}
return(EOF);
#endif
}
/*
* Hang up the 'fone.
*/
int
hangup()
{
/* Restore terminal settings on dialout line */
static char a[] = "+++",
o[] = "OK",
h[] = "ATH0\r";
int retry = 5;
while (instr(o, strlen(o)) && retry--)
xwrite(a, strlen(a)-1);
xwrite(h, strlen(h)-1);
if (instr(o, strlen(o)) || !retry)
DEBUG(0, "uucico: problem hanging up\n", 0);
#ifndef COMPORT
close(fdtty);
#else
set_tty(0,0,0,MDSBL); /* Hang up like a nice programme */
reset_tty(); /* Pop the serial port's pram off */
uninit_comm(); /* Uninit the interrupt */
#endif
sleep(3); /* Wait with DTR down */
exit(0);
}
/* CP/M and MSDOS and ST need these routines. Probably should use
* the new names, but for now...
*/
bzero(s, cnt)
register char *s;
register int cnt;
{
register int i;
for (i = 0; i < cnt; i++) {
*s++ = '\0';
}
}
bcopy(from, to, cnt)
register char *from;
register char *to;
register int cnt;
{
register int i;
for (i = 0; i < cnt; i++) {
*to++ = *from++;
}
}
/*
* Function to clean up all the loose ends if the user wishes to
* abort UUSLAVE
*/
int handler()
{
printf("\nAborting UUSLAVE\n");
#ifdef COMPORT
set_tty(0,0,0,MDSBL); /* drop DTR to hang up */
sleep(2); /* let it settle */
reset_tty(); /* put the port back in condition it
was before running the programme */
#endif
exit(1); /* AWWAAAYY! */
}
#ifdef COMPORT
/*
* MSDOS routines for handling the comm port.
*
* get_time(n)
* TIME_PTR n;
*
* fills timetype structure n with current time using DOS interrupt 21
*
*/
get_time(n)
TIME_PTR n;
{
union REGS inregs;
union REGS outregs;
inregs.h.ah = GET_TIME;
int86(DOS_INT, &inregs, &outregs);
n->hour = outregs.h.ch;
n->minute = outregs.h.cl;
n->sec = outregs.h.dh;
n->hsec = outregs.h.dl;
return(0);
}
sleep(x)
int x;
{
int i;
unsigned s;
TIME n; /* current time record */
i = 0;
get_time(&n);
s = n.sec;
while (i < x){
while (s == n.sec)
get_time(&n);
s = n.sec;
++i;
}
}
#endif
/*
* Returns 1 if a matching file was found, 0 if not.
*/
find(pathname,flag,pxfbuf)
char *pathname;
int flag;
struct _xfbuf *pxfbuf;
{
union REGS inregs, outregs;
inregs.x.dx = (unsigned int) pxfbuf;
inregs.h.ah = 26;
intdos(&inregs,&outregs); /* set up DTA */
inregs.x.dx = (unsigned int) pathname;
inregs.x.cx = 22; /* the search atribute */
if (flag == 0)
inregs.h.ah = 78; /* if this is the first time FIND FIRST */
else {
inregs.h.ah = 79; /* if this is not the first time FIND NEXT */
flag = 1;
}
intdos(&inregs,&outregs);
if ((outregs.x.ax == 18) || (outregs.x.ax == 3))
return (0);
return(1);
}
/*
* Create a temporary file name for receiving a file into.
* "name" is the name we will actually eventually want to use for the file.
* We currently ignore it, but some OS's that can't move files around
* easily might want to e.g. put the temp file into the same directory
* that this file is going into.
*
* FIXME:
* This interface should be able to return a "possible" filename, and
* be re-called if the name is already in use, to get another.
* This avoids checking here whether the name is good -- saving system calls.
*/
char *
temp_filename(name)
register char *name;
{
static char tname[NAMESIZE];
char *t;
if ((t = tmpnam(NULL)) != NULL && !curtemp)
bcopy(t,tname,strlen(t));
else
sprintf(tname,"%s/%s/uutemp.$$$", spool_path, host_name);
DEBUG(2,"Using temp file %s\n", tname);
return tname;
}
/*
* Transform a filename from Unix format into a local
* filename that will work in the local file system.
*
* E.g. LCK..hoptoad --> hoptoad\.LCK
* C.hoptoadA1234 --> hoptoad\A1234.C
* etc.
* FIXME: this is not done for anything but C. and D. files currently.
* It does NOT work for LCK. and STST. files!
*/
char *
munge_filename(name)
register char *name;
{
register char *p;
static char buffer[NAMESIZE+SLOP];
char mname[MAX_HOST]; /* master's name */
char cwdir[NAMESIZE]; /* current working director */
char ufname[UFNAMESIZE + 1]; /* distinctive 5 char UU file ID */
int i; /* counter */
/* FIXME there is a problem when host names are shorter than six chars */
/* ok, fixed, gmp (see also getname() ) */
DEBUG(4,"Munge_filename input: %s\n", name);
if (name[0] == '/' || name[0] == '~' || name[1] != '.') {
/* Don't munge things that start with / or ~, or which
* aren't uucp internal file names with 2nd char dot */
#ifdef NOTDEF
/* This bit of code was in local_send_file. I'm not sure why.
* If it belongs anywhere, it belongs here, but I don't see why it exists.
* If it's going to stay here, it needs a bit of conversion.
*/
if (strstr(srcnam, "/\\"))
strcpy (temp, srcnam); /* if already contains path info */
else {
strcpy (temp, host_name);
strcat (temp, "\\");
strcat (temp, srcnam); /* otherwise ref to hosts' subdir */
}
#endif
p = name;
} else {
/*
* This is a uucp-internal C., D., or other name.
* Munge the hell out of it. For MSDOS, we can't
* handle the 14-character names of Unix, so change
* it to:
*
* L.hostGNNNN -> host/GNNNN.L
*/
bzero(cwdir, sizeof cwdir);
bzero(ufname, sizeof ufname);
i = strlen(name);
strncpy(mname, &name[2], i - (2 + UFNAMESIZE));
mname[i - (2 + UFNAMESIZE)] = '\0';
strcpy(buffer, spool_path);
strcat(buffer, "/");
strcat(buffer, mname); /* get host's directory name */
/*
* Quick (?) test to see if we already have a directory
* for this host.
*/
getcwd(cwdir,NAMESIZE); /* save current directory */
if (chdir(buffer) == -1) { /* If new dir doesn't exist, */
if (mkdir(buffer) == -1) { /* ... make one */
DEBUG(0, "Can't make new directory %s\n", buffer);
} else {
DEBUG(4, "Making new directory %s\n", buffer);
}
} else
chdir(cwdir); /* pop back to the home directory */
/* build actual file name */
p = buffer + strlen(buffer);
for(i = 0; i <= UFNAMESIZE; i++)
ufname[UFNAMESIZE - i] = name[strlen(name) - i];
*p++ = '/';
strncpy(p, &name[i - UFNAMESIZE], UFNAMESIZE); /* GNNNN */
strcat(p, ".");
p[strlen(p)] = name[0]; /* C, D, X */
p = buffer;
}
DEBUG(4, "Munge_filename output: %s\n", p);
return p;
}
/*
* Uucp work queue scan. For calling sequences, see sysdep.h.
*/
static DIR *workdir = (DIR *)NULL;
static struct _xfbuf xfbuf;
static int workfile; /* Do we have one in xfbuf? */
static char workhost[MAX_HOST+1];
static int workhlen;
static char workfirst = 0;
void
work_done()
{
if (workdir)
closedir(workdir);
workdir = (DIR *) NULL;
workfile = 0;
workfirst = 0;
}
int
work_scan(host, type)
char *host;
char *type; /* E.g. "C", "X", "LCK" */
{
/* Null argument produces all hostnames */
if (!host || *host) host="*";
/* If called twice in a row, don't thrash the disk again */
if (!strcmp(workhost, host) && workfile)
return 1;
if (workdir) work_done(); /* Clean up prev call */
workfirst = 1; /* Initialize for work_next */
workhlen = strlen(host);
if (workhlen > sizeof (workhost) -1) abort();
strcpy(workhost, host);
if (workhlen > 7) workhlen = 7; /* Unix uucp limit */
strncpy(tempnam, workhost, workhlen);
strcpy(tempnam+workhlen, "/*.");
strcat(tempnam+workhlen+ 3, type);
workfile = find(tempnam, FALSE, &xfbuf);
if (!workfile) {
DEBUG(8, "work_scan readdir null\n", 0);
work_done();
return 0; /* No work */
}
return 1;
}
static int
work_look()
{
int len;
for (;;) {
workfile = find(tempnam, TRUE, &xfbuf);
if (!workfile) {
DEBUG(8, "work_look readdir null\n", 0);
work_done();
return 0; /* No work */
}
DEBUG(8, "work_look readdir %s\n", xfbuf.name);
/* FIXME, check grade letter! */
return 1; /* Found work */
}
/* NOTREACHED */
}
char *
work_next()
{
/* Space for: "TYPE.hostnameA1234" */
static char subhack[6 +MAX_HOST + UFNAMESIZE + SLOP];
if (!workfirst) {
if (!workfile || !work_look())
return (char *)NULL;
}
workfirst = 0;
/* FIXME, This probably fails for STST and LCK files. */
p = index(xfbuf.name, '.');
if (!p) abort(); /* There must be a filename extension */
*p = '\0';
sprintf(subhack, "%s.%s%s", p+1, workhost, xfbuf.name);
return subhack;
}
/*
* Routine to return a string that gives the current date and time, and
* identifies the current process, if on a multiprocess system.
*
* MSDOS multitasking is only a year away, so keep the getpid()...
*/
char *
time_and_pid()
{
long clock;
struct tm *tm;
static int ourpid = 0;
static char format[] = "%d/%d-%d:%02d:%02d-%d";
static char outbuf[sizeof(format)];
(void) time(&clock);
tm = localtime(&clock);
if (ourpid == 0)
ourpid = getpid();
sprintf(outbuf, format,
tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
ourpid);
return outbuf;
}